#include "stdafx.h"

#undef GetCurrentDirectory
#include "Property.h"
#include "interop.h"
//#include "..\SEPEditor.h"
//#include "Entity/mesh_property.h"

using namespace System::Collections::Generic;
using namespace interop;
namespace interop
{
	ref class StringWrapper
	{
	public:
		String^ str;
		StringWrapper()
		{
			str=gcnew String("");
		}

		StringWrapper(String^ s)
		{
			str=s;
		}

		operator String^()
		{
			return str;
		}
	};
	String^ format_json_string(String^ src)
	{
		array<String^>^ l;
		{

			array<wchar_t>^ separator=gcnew array<wchar_t>(2);
			separator[0]='\n';
			separator[1]='\r';
			l=src->Split(separator);
		}
		int indent=0;

		String^ ret;

		for each (String^ s in l)
		{
			if (!s->Length)
				continue;
			s=s->Replace("\t","");
			if (s[0]=='}')
				--indent;

			if (indent<0)
				indent=0;

			String^ s1 = "";
			for (int n=0; n<indent; ++n)
				s1+="  ";

			s1+=s;

			if (s[0]=='{')
				++indent;

			ret+=s1+"\r\n";
		}

		return ret;

	}

	public ref class intprop:public MyPropertyTable
	{
	public:
		intprop():MyPropertyTable(nullptr,nullptr)
		{
			int l=0;
			Properties->Add(gcnew PropertyGridEx::PropertySpec("VALUE", Int32::typeid, "Value", nullptr, l));
			(*this)["VALUE"]=l;
		}

		intprop(MyPropertyTable^p, entity_t* e,int v):MyPropertyTable(p,e)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("VALUE", Int32::typeid, "Value", nullptr, v));
			(*this)["VALUE"]=v;
		}

		int get()
		{
			return (int)(*this)["VALUE"];
		}

		virtual String^ ToString() override
		{
			String^ s = gcnew String("")+(int)(*this)["VALUE"];
			return s;
		}
	};

	public ref class floatprop:public MyPropertyTable
	{
	public:
		floatprop():MyPropertyTable(nullptr,nullptr)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("VALUE", Single::typeid, "Value", nullptr, 0.0f));
			(*this)["VALUE"]=0.0f;
		}

		floatprop(MyPropertyTable^p, entity_t* e,float v):MyPropertyTable(p,e)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("VALUE", Single::typeid, "Value", nullptr, v));
			(*this)["VALUE"]=v;
		}

		float get()
		{
			return (float)(*this)["VALUE"];
		}

		virtual String^ ToString() override
		{
			String^ s = gcnew String("")+get();
			return s;
		}
	};


	public ref class float2prop:public MyPropertyTable
	{		
	public:
		float2prop():MyPropertyTable(nullptr,nullptr)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("X", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Y", Single::typeid, "Position", nullptr, 0.0f));
			(*this)["X"]=0.0f;
			(*this)["Y"]=0.0f;
		}

		float2prop(MyPropertyTable^p, entity_t* e,float2 v):MyPropertyTable(p,e)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("X", Single::typeid, "Position", nullptr, v.x));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Y", Single::typeid, "Position", nullptr, v.y));
			(*this)["X"]=v.x;
			(*this)["Y"]=v.y;
		}

		float2 get()
		{
			return float2((float)(*this)["X"],(float)(*this)["Y"]);
		}

		void set(float2 v)
		{
			(*this)["X"]=v.x;
			(*this)["Y"]=v.y;
		}

		virtual String^ ToString() override
		{
			String^ s = gcnew String("");
			float2 pos;
			pos.set((float)(*this)["X"],(float)(*this)["Y"]);
			s=pos.x+";"+pos.y;

			return s;
		}
	};
/*
	public ref class int2prop:public MyPropertyTable
	{		
	public:
		int2prop():MyPropertyTable(nullptr,nullptr)
		{
			int nulla=0;
			Properties->Add(gcnew PropertyGridEx::PropertySpec("X", Int32::typeid, "Position", nullptr, nulla));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Y", Int32::typeid, "Position", nullptr, nulla));
			(*this)["X"]=nulla;
			(*this)["Y"]=nulla;
		}

		int2prop(MyPropertyTable^p, entity_t* e,int2 v):MyPropertyTable(p,e)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("X", Int32::typeid, "Position", nullptr, v.x));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Y", Int32::typeid, "Position", nullptr, v.y));
			(*this)["X"]=v.x;
			(*this)["Y"]=v.y;
		}

		int2 get()
		{
			return int2((int)(*this)["X"],(int)(*this)["Y"]);
		}

		void set(int2 v)
		{
			(*this)["X"]=v.x;
			(*this)["Y"]=v.y;
		}

		virtual String^ ToString() override
		{
			String^ s = gcnew String("");
			int2 pos;
			pos.set((int)(*this)["X"],(int)(*this)["Y"]);
			s=pos.x+";"+pos.y;

			return s;
		}
	};

	public ref class sphereprop:public MyPropertyTable
	{		
	public:
		sphereprop():MyPropertyTable(nullptr,nullptr)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("CENTER X", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("CENTER Y", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("CENTER Z", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("RADIUS", Single::typeid, "Position", nullptr, 0.0f));

			(*this)["CENTER X"]=0.0f;
			(*this)["CENTER Y"]=0.0f;
			(*this)["CENTER Z"]=0.0f;

			(*this)["RADIUS"]=0.0f;
		}

		sphereprop(float3 v, float r):MyPropertyTable(nullptr,nullptr)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("CENTER X", Single::typeid, "Position", nullptr, v.x));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("CENTER Y", Single::typeid, "Position", nullptr, v.y));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("CENTER Z", Single::typeid, "Position", nullptr, v.z));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("RADIUS", Single::typeid, "Position", nullptr, r));
			(*this)["CENTER X"]=v.x;
			(*this)["CENTER Y"]=v.y;
			(*this)["CENTER Z"]=v.z;

			(*this)["RADIUS"]=r;
		}

		float3 get_center()
		{
			return float3((float)(*this)["CENTER X"],(float)(*this)["CENTER Y"],(float)(*this)["CENTER Z"]);
		}

		float get_radius()
		{
			return (float)(*this)["RADIUS"];
		}

		virtual String^ ToString() override
		{
			String^ s = gcnew String("");
			float3 pos=get_center();
			float ext=get_radius();
			s="["+pos.x+";"+pos.y+";"+pos.z+"]["+ext+"]";

			return s;
		}
	};
*/


	public ref class float3prop:public MyPropertyTable
	{		
	public:
		float3prop():MyPropertyTable(nullptr,nullptr)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("X", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Y", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Z", Single::typeid, "Position", nullptr, 0.0f));
			(*this)["X"]=0.0f;
			(*this)["Y"]=0.0f;
			(*this)["Z"]=0.0f;
		}

		float3prop(MyPropertyTable^p, entity_t* e,float3 v):MyPropertyTable(p,e)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("X", Single::typeid, "Position", nullptr, v.x));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Y", Single::typeid, "Position", nullptr, v.y));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Z", Single::typeid, "Position", nullptr, v.z));
			(*this)["X"]=v.x;
			(*this)["Y"]=v.y;
			(*this)["Z"]=v.z;
		}

		float3 get()
		{
			return float3((float)(*this)["X"],(float)(*this)["Y"],(float)(*this)["Z"]);
		}

		void set(float3 v)
		{
			(*this)["X"]=v.x;
			(*this)["Y"]=v.y;
			(*this)["Z"]=v.z;
		}

		virtual String^ ToString() override
		{
			String^ s = gcnew String("");
			float3 pos;
			pos.set((float)(*this)["X"],(float)(*this)["Y"],(float)(*this)["Z"]);
			s=pos.x+";"+pos.y+";"+pos.z;

			return s;
		}

	};

	public ref class float4prop:public MyPropertyTable
	{		
	public:
		float4prop():MyPropertyTable(nullptr,nullptr)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("X", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Y", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Z", Single::typeid, "Position", nullptr, 0.0f));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("W", Single::typeid, "Position", nullptr, 0.0f));
			(*this)["X"]=0.0f;
			(*this)["Y"]=0.0f;
			(*this)["Z"]=0.0f;
			(*this)["W"]=0.0f;
		}

		float4prop(MyPropertyTable^p, entity_t* e,float4 v):MyPropertyTable(p,e)
		{
			Properties->Add(gcnew PropertyGridEx::PropertySpec("X", Single::typeid, "Position", nullptr, v.x));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Y", Single::typeid, "Position", nullptr, v.y));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("Z", Single::typeid, "Position", nullptr, v.z));
			Properties->Add(gcnew PropertyGridEx::PropertySpec("W", Single::typeid, "Position", nullptr, v.w));
			(*this)["X"]=v.x;
			(*this)["Y"]=v.y;
			(*this)["Z"]=v.z;
			(*this)["W"]=v.w;
		}

		float4 get()
		{
			return float4((float)(*this)["X"],(float)(*this)["Y"],(float)(*this)["Z"],(float)(*this)["W"]);
		}

		void set(float4 v)
		{
			(*this)["X"]=v.x;
			(*this)["Y"]=v.y;
			(*this)["Z"]=v.z;
			(*this)["W"]=v.w;
		}

		virtual String^ ToString() override
		{
			String^ s = gcnew String("");
			float4 pos;
			pos.set((float)(*this)["X"],(float)(*this)["Y"],(float)(*this)["Z"],(float)(*this)["W"]);
			s=pos.x+";"+pos.y+";"+pos.z+";"+pos.w;

			return s;
		}

	};



	void add_property_to_grid(entity_t* i_Node,property_t* i_GameProperty,const char* i_displayname,String^ category_name,MyPropertyTable^ prop_collection)
	{
		String^ desc=gcnew String(i_GameProperty->m_description);
		String^ prop_name=gcnew String(i_displayname);

		switch (i_GameProperty->get_type())
		{
		case prop_json_property:
			{
				json_object_t* o=&i_GameProperty->get<json_object_t>(i_Node);
				string s=save_json_to_string(o,false);
				String^ str=format_json_string(gcnew String(s.c_str()));
				

				PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
					String::typeid,
					category_name,
					desc,
					str,
					UITextboxEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid);
				prop_collection->Properties->Add(ps);

				prop_collection[prop_name]=str;
				break;
			}
		case prop_int:
			{
				if (i_GameProperty->data)
				{
					ArrayList^ al=gcnew ArrayList;
					int_data_t* s=(int_data_t*)i_GameProperty->data;
					al->Add(gcnew PropertyGridEx::TrackbarEditorAttr(s->minimum,s->maximum,prop_name));
					PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
						Int32::typeid,
						category_name,
						desc,
						i_GameProperty->get<int>(i_Node),
						UITrackbarEditor::typeid,
						System::Drawing::Design::UITypeEditor::typeid);
					ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);
					prop_collection->Properties->Add(ps);
				}
				else
					prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, Int32::typeid, category_name, desc, i_GameProperty->get<int>(i_Node)));
				prop_collection[prop_name]=i_GameProperty->get<int>(i_Node);
				break;
			}

		case prop_float:
			{
				if (i_GameProperty->data)
				{
					ArrayList^ al=gcnew ArrayList;
					float_data_t* s=(float_data_t*)i_GameProperty->data;
					al->Add(gcnew PropertyGridEx::TrackbarEditorAttr(s->minimum,s->maximum,s->granularity,prop_name,false));
					PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
						Single::typeid,
						category_name,
						desc,
						i_GameProperty->get<int>(i_Node),
						UITrackbarEditor::typeid,
						System::Drawing::Design::UITypeEditor::typeid);
					ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);
					prop_collection->Properties->Add(ps);
				}
				else
					prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, Single::typeid, category_name, desc, i_GameProperty->get<float>(i_Node)));
				prop_collection[prop_name]=i_GameProperty->get<float>(i_Node);
				break;
			}

		case prop_angle:
			{
				float val=((angle_property_t*)i_GameProperty)->get_angle(i_Node);

				if (i_GameProperty->data)
				{
					ArrayList^ al=gcnew ArrayList;
					float_data_t* s=(float_data_t*)i_GameProperty->data;
					al->Add(gcnew PropertyGridEx::TrackbarEditorAttr(s->minimum,s->maximum,s->granularity,prop_name,true));
					PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
						Single::typeid,
						category_name,
						desc,
						val,
						UITrackbarEditor::typeid,
						System::Drawing::Design::UITypeEditor::typeid);
					ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);
					prop_collection->Properties->Add(ps);
				}
				else
					prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, "System.Single", category_name, desc, val));

				prop_collection[prop_name]=val;
				break;
			}

		case prop_stringlist:
			{
				vector<string>& data=i_GameProperty->get < vector<string> >(i_Node);
//				array<String^>^ val=gcnew array<String^>(data.size());
				Generic::List<String^>^ valami=gcnew Generic::List<String^>();

				for (unsigned n=0; n<data.size(); ++n)
				{
					valami->Add(gcnew String(data[n].c_str()));
//					val[n]=gcnew String(data[n].c_str());
				}

				PropertyGridEx::UIStringList^ val=gcnew PropertyGridEx::UIStringList(valami);
//				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, List<StringWrapper^>::typeid, category_name, desc, val
//					,array<String^>::typeid
//					,System::Drawing::Design::UITypeEditor::typeid
//					,ExpandableObjectConverter::typeid
//					));

				PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
					String::typeid,
					category_name,
					desc,
					val,
					UIStringlistEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid);
				prop_collection->Properties->Add(ps);


				prop_collection[prop_name]=val;
				break;
			}
		case prop_string:
			{
				String^ val=gcnew String(i_GameProperty->get<string>(i_Node).c_str());
				if (i_GameProperty->data)
				{
					ArrayList^ al=gcnew ArrayList;
					string_data_t* s=(string_data_t*)i_GameProperty->data;
					al->Add(gcnew PropertyGridEx::FileNameEditorAttr(gcnew String(s->filter),gcnew String(s->initdir)));
					PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
						String::typeid,//PropertyGridEx::UIFileNameEditor::typeid,
						category_name,
						desc,
						val,
						PropertyGridEx::UIFileNameEditor::typeid,
						System::Drawing::Design::UITypeEditor::typeid);
					ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);
					prop_collection->Properties->Add(ps);
				}
				else
				{
					prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, System::String::typeid, category_name, desc, val));
				}

				prop_collection[prop_name]=val;
				break;
			}
		case prop_stringhash:
			{
#if 0
				String^ val=gcnew String(i_GameProperty->get<stringhash>(i_Node).c_str());
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, System::String::typeid, category_name, desc, val));
				prop_collection[prop_name]=val;
#else
				String^ val=gcnew String(i_GameProperty->get<stringhash>(i_Node).c_str());
				if (i_GameProperty->data)
				{
					ArrayList^ al=gcnew ArrayList;
					string_data_t* s=(string_data_t*)i_GameProperty->data;
					al->Add(gcnew PropertyGridEx::FileNameEditorAttr(gcnew String(s->filter),gcnew String(s->initdir)));
					PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
						String::typeid,//PropertyGridEx::UIFileNameEditor::typeid,
						category_name,
						desc,
						val,
						PropertyGridEx::UIFileNameEditor::typeid,
						System::Drawing::Design::UITypeEditor::typeid);
					ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);
					prop_collection->Properties->Add(ps);
				}
				else
				{
					prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, System::String::typeid, category_name, desc, val));
				}

				prop_collection[prop_name]=val;
#endif
				break;
			}

		case prop_float3:
			{
				float3 val=i_GameProperty->get<float3>(i_Node);
				float3prop^ newbag=gcnew float3prop(prop_collection,i_Node,val);
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, float3prop::typeid, category_name, desc, newbag,
				System::Drawing::Design::UITypeEditor::typeid,
				ExpandableObjectConverter::typeid));
				newbag->UserData["X"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["Y"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["Z"]=gcnew PropertyNode(i_GameProperty,prop_name);

				prop_collection[prop_name]=newbag;
				break;
			}
		case prop_float4:
			{
				float4 val=i_GameProperty->get<float4>(i_Node);
				float4prop^ newbag=gcnew float4prop(prop_collection,i_Node,val);
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, float4prop::typeid, category_name, desc, newbag,
					System::Drawing::Design::UITypeEditor::typeid,
					ExpandableObjectConverter::typeid));
				newbag->UserData["X"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["Y"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["Z"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["W"]=gcnew PropertyNode(i_GameProperty,prop_name);

				prop_collection[prop_name]=newbag;
				break;
			}
		case prop_float2:
			{
				float2 val=i_GameProperty->get<float2>(i_Node);
				float2prop^ newbag=gcnew float2prop(prop_collection,i_Node,val);
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, MyPropertyTable::typeid, category_name, desc, newbag,
					System::Drawing::Design::UITypeEditor::typeid,
					ExpandableObjectConverter::typeid));
				newbag->UserData["X"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["Y"]=gcnew PropertyNode(i_GameProperty,prop_name);
				prop_collection[prop_name]=newbag;
				break;
			}
/*
		case prop_int2:
			{
				int2 val=i_GameProperty->get<int2>(i_Node);
				int2prop^ newbag=gcnew int2prop(prop_collection,i_Node,val);
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, MyPropertyTable::typeid, category_name, desc, newbag,
					System::Drawing::Design::UITypeEditor::typeid,
					ExpandableObjectConverter::typeid));
				newbag->UserData["X"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["Y"]=gcnew PropertyNode(i_GameProperty,prop_name);
				prop_collection[prop_name]=newbag;
				break;
			}
*/

		case prop_color4f:
			{
				color4f& c=i_GameProperty->get<color4f>(i_Node);
				ColorProp^ cp=gcnew ColorProp(&c,i_Node,gcnew String(i_GameProperty->name.c_str()));
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, float4prop::typeid, category_name, desc, cp,
					UIColorEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid));

				prop_collection[prop_name]=cp;
				break;
			}



		case prop_float4x4:
			{
				float4x4 val=i_GameProperty->get<float4x4>(i_Node);
				float4x4prop^ newbag=gcnew float4x4prop(prop_collection,i_Node,val);
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, float4x4prop::typeid, category_name, desc, newbag,
					System::Drawing::Design::UITypeEditor::typeid,
					ExpandableObjectConverter::typeid));
				newbag->UserData["X"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["Y"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["Z"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["YAW"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["PITCH"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["ROLL"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["SCALE X"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["SCALE Y"]=gcnew PropertyNode(i_GameProperty,prop_name);
				newbag->UserData["SCALE Z"]=gcnew PropertyNode(i_GameProperty,prop_name);
				prop_collection[prop_name]=newbag;
				break;
			}

		case prop_bool:
			{
				bool val=i_GameProperty->get<bool>(i_Node);
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, System::Boolean::typeid, category_name, desc, val));
				prop_collection[prop_name]=val;
				break;
			}

/*
		case prop_tick:
			{
				int val=i_GameProperty->get<int>(i_Node)/60;
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, Single::typeid, category_name, desc, val));
				prop_collection[prop_name]=val;
				break;
			}
*/
		case prop_enum:
			{
				Generic::List<String^> ^ list=gcnew Generic::List<String^>;
				char** strlist=(char**)i_GameProperty->data;
				int size; for (size=0; strlist[size];size++);

				int selected_index=i_GameProperty->get<int>(i_Node);
				for (int i = 0; i < size; i++)
				{
					list->Add(gcnew String(strlist[i]));
//					list->Items->Add(gcnew PropertyGridEx::CustomItem(i, gcnew String(strlist[i]), i==selected_index));
				}

				PropertyGridEx::PropertySpec^ ps=
				gcnew PropertyGridEx::PropertySpec(prop_name,
					String::typeid,
					category_name,
					desc,
					gcnew String(strlist[selected_index]),
					PropertyGridEx::UIListBoxEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid);


				ArrayList^ al=gcnew ArrayList;
				al->Add(gcnew PropertyGridEx::ListBoxAttribute(gcnew PropertyGridEx::UIStringList(list)));
				ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);
				prop_collection->Properties->Add(ps);


				prop_collection[prop_name] = gcnew String(strlist[selected_index]);

				break;
			}
/*
		case prop_mesh:
			{
				String^ model_name=gcnew String(i_GameProperty->get<sep3d::hierarchy_t>(i_Node).m_name.c_str());
				PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
					String::typeid,
					category_name,
					desc,
					model_name,
					PropertyGridEx::UIFileNameEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid);

				ArrayList^ al=gcnew ArrayList;
				al->Add(gcnew PropertyGridEx::FileNameEditorAttr("3d files(*.drs;*.x;*.dae;*.sph)|*.drs;*.x;*.dae;*.sph",""));
				ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);
				prop_collection->Properties->Add(ps);


				prop_collection[prop_name]=model_name;
				break;
			}
*/
			/*
		case prop_TREF_TEXTURE:
			{
				String^ texname=gcnew String(i_GameProperty->get<TREF_TEXTURE>(i_Node) ? i_GameProperty->get<TREF_TEXTURE>(i_Node)->GetName() : "");
				PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
					String::typeid,//PropertyGridEx::UIFileNameEditor::typeid,
					category_name,
					desc,
					texname,
					PropertyGridEx::UIFileNameEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid);

				ArrayList^ al=gcnew ArrayList;
				al->Add(gcnew PropertyGridEx::FileNameEditorAttr("texture files(*.dds;*.tga;*.png;*.jpg)|*.dds;*.tga;*.png;*.jpg","Textures"));
				ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);

				prop_collection->Properties->Add(ps);


				prop_collection[prop_name]=texname;
				break;
			}
		case prop_sound:
			{
				String^ soundname=gcnew String(i_GameProperty->get<sound_object_t>(i_Node).name.c_str());
				PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
					PropertyGridEx::UIFileNameEditor::typeid,
					category_name,
					desc,
					soundname,
					PropertyGridEx::UIFileNameEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid);

				ArrayList^ al=gcnew ArrayList;
				al->Add(gcnew PropertyGridEx::FileNameEditorAttr("Sound files(*.wav;*.mp3)|*.wav;*.mp3","Sounds"));
				ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);

				prop_collection->Properties->Add(ps);


				prop_collection[prop_name]=soundname;
				break;
			}

*/
/*
		case prop_natural_spline_t:
			{
				natural_spline_t& v=i_GameProperty->get<natural_spline_t>(i_Node);
				NaturalSplineObjectProp^ o=gcnew NaturalSplineObjectProp(&v,i_Node);
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, UINaturalSplineEditor::typeid, category_name, desc, o,
					UINaturalSplineEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid));

				prop_collection[prop_name]=o;
				break;
			}

		case prop_spherearray:
			{
				prop_array_t<sphere_t>& v=i_GameProperty->get<prop_array_t<sphere_t>>(i_Node);
				SphereArrayProp^ o=gcnew SphereArrayProp(&v,i_Node);
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, UISphereArrayEditor::typeid, category_name, desc, o,
					UISphereArrayEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid));

				prop_collection[prop_name]=o;
				break;
			}

*/
		case prop_array:
			{
				array_property_t* p=(array_property_t*)i_GameProperty;
				prop_array_base_t& a=i_GameProperty->get<prop_array_base_t>(i_Node);
				int size=a.get_size();

				switch (p->base_property->get_type())
				{
				case prop_int:
					{
						array<intprop^>^ intarray=gcnew array<intprop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							int val=p->base_property->get<int>((entity_t*)a.get_elem_ptr(n));
							intprop^ newbag=gcnew intprop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, array<intprop^>::typeid, category_name, desc, intarray));

						prop_collection[prop_name]=intarray;
						break;

						break;
					}
/*
				case prop_tick:
					{
						array<floatprop^>^ intarray=gcnew array<floatprop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float val=(float)p->base_property->get<int>((entity_t*)a.get_elem_ptr(n))/60;
							floatprop^ newbag=gcnew floatprop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, array<floatprop^>::typeid, category_name, desc, intarray));
						prop_collection[prop_name]=intarray;
						break;
					}
*/
				case prop_float:
					{
						array<floatprop^>^ intarray=gcnew array<floatprop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float val=p->base_property->get<float>((entity_t*)a.get_elem_ptr(n));
							floatprop^ newbag=gcnew floatprop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, array<floatprop^>::typeid, category_name, desc, intarray));
						prop_collection[prop_name]=intarray;
						break;
					}
				case prop_float2:
					{
						array<float2prop^>^ intarray=gcnew array<float2prop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float2 val=p->base_property->get<float2>((entity_t*)a.get_elem_ptr(n));
							float2prop^ newbag=gcnew float2prop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, array<float2prop^>::typeid, category_name, desc, intarray));

						prop_collection[prop_name]=intarray;
						break;
					}
/*
				case prop_int2:
					{
						array<int2prop^>^ intarray=gcnew array<int2prop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							int2 val=p->base_property->get<int2>((entity_t*)a.get_elem_ptr(n));
							int2prop^ newbag=gcnew int2prop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, array<int2prop^>::typeid, category_name, desc, intarray));

						prop_collection[prop_name]=intarray;
						break;
					}
*/
				case prop_float3:
					{
						array<float3prop^>^ intarray=gcnew array<float3prop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float3 val=p->base_property->get<float3>((entity_t*)a.get_elem_ptr(n));
							float3prop^ newbag=gcnew float3prop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, array<float3prop^>::typeid, category_name, desc, intarray));

						prop_collection[prop_name]=intarray;
						break;
					}
				case prop_float4:
					{
						array<float4prop^>^ intarray=gcnew array<float4prop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float4 val=p->base_property->get<float4>((entity_t*)a.get_elem_ptr(n));
							float4prop^ newbag=gcnew float4prop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, array<float4prop^>::typeid, category_name, desc, intarray));

						prop_collection[prop_name]=intarray;
						break;
					}

				case prop_color4f:
				{
					break;
				}

/*
				case prop_sphere:
					{
						array<sphereprop^>^ intarray=gcnew array<sphereprop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							sphere_t val=p->base_property->get<sphere_t>((entity_t*)a.get_elem_ptr(n));
							sphereprop^ newbag=gcnew sphereprop(val.center,val.radius);
							intarray[n]=newbag;
						}
						prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, array<sphereprop^>::typeid, category_name, desc, intarray));
//							,array<sphereprop^>::typeid,
//							System::Drawing::Design::UITypeEditor::typeid
							
//							));//,

						prop_collection[prop_name]=intarray;
						break;
					}
*/

				default:
					ASSERT(0);
				}
				break;
			}

		default:
			ASSERT(0);
		}

		prop_collection->UserData[prop_name]=gcnew PropertyNode(i_GameProperty,prop_name);
	}








	void set_property_in_grid(entity_t* i_Node,property_t* i_GameProperty,const char* i_displayname,String^ category_name,MyPropertyTable^ prop_collection)
	{
		String^ desc=gcnew String(i_GameProperty->m_description);
		String^ prop_name=gcnew String(i_displayname);

		switch (i_GameProperty->get_type())
		{
		case prop_json_property:
			{
				json_object_t* o=&i_GameProperty->get<json_object_t>(i_Node);
				string s=save_json_to_string(o,false);
				prop_collection[prop_name]=format_json_string(gcnew String(s.c_str()));
				break;

			}
		case prop_int:
			{
				prop_collection[prop_name]=i_GameProperty->get<int>(i_Node);
				break;
			}

		case prop_float:
			{
				prop_collection[prop_name]=i_GameProperty->get<float>(i_Node);
				break;
			}

		case prop_angle:
			{
				float val=((angle_property_t*)i_GameProperty)->get_angle(i_Node);
				prop_collection[prop_name]=val;
				break;
			}

		case prop_stringlist:
			{
				vector<string>& data=i_GameProperty->get < vector<string> >(i_Node);
//				array<String^>^ val=gcnew array<String^>(data.size());
				PropertyGridEx::UIStringList^ val=gcnew PropertyGridEx::UIStringList();

				for (unsigned n=0; n<data.size(); ++n)
				{
//					val[n]=gcnew String(data[n].c_str());
					val->Value->Add(gcnew String(data[n].c_str()));
				}
				prop_collection[prop_name]=val;
				break;
			}
		case prop_string:
			{
				String^ val=gcnew String(i_GameProperty->get<string>(i_Node).c_str());
				prop_collection[prop_name]=val;
				break;
			}
		case prop_stringhash:
			{
				String^ val=gcnew String(i_GameProperty->get<stringhash>(i_Node).c_str());
				prop_collection[prop_name]=val;
				break;
			}

		case prop_float3:
			{
				float3 val=i_GameProperty->get<float3>(i_Node);
				((float3prop^)prop_collection[prop_name])->set(val);
				break;
			}
		case prop_float4:
			{
				float4 val=i_GameProperty->get<float4>(i_Node);
				((float4prop^)prop_collection[prop_name])->set(val);
				break;
			}
		case prop_float2:
			{
				float2 val=i_GameProperty->get<float2>(i_Node);
				((float2prop^)prop_collection[prop_name])->set(val);
				break;
			}
/*
		case prop_int2:
			{
				int2 val=i_GameProperty->get<int2>(i_Node);
				((int2prop^)prop_collection[prop_name])->set(val);
				break;
			}

*/
		case prop_color4f:
			{/*
				color4f& c=i_GameProperty->get<color4f>(i_Node);
				ColorProp^ cp=gcnew ColorProp(&c,i_Node,gcnew String(i_GameProperty->get_name()));
				prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(prop_name, UIColorEditor::typeid, category_name, desc, cp,
					UIColorEditor::typeid,
					System::Drawing::Design::UITypeEditor::typeid));

				prop_collection[prop_name]=cp;*/
				break;
			}



		case prop_float4x4:
			{
				float4x4 val=i_GameProperty->get<float4x4>(i_Node);
				((float4x4prop^)prop_collection[prop_name])->set(val);
				break;
			}

		case prop_bool:
			{
				bool val=i_GameProperty->get<bool>(i_Node);
				prop_collection[prop_name]=val;
				break;
			}

/*
		case prop_tick:
			{
				int val=i_GameProperty->get<int>(i_Node)/60;
				prop_collection[prop_name]=val;
				break;
			}
*/
		case prop_enum:
			{
				char** strlist=(char**)i_GameProperty->data;
				int selected_index=i_GameProperty->get<int>(i_Node);
				prop_collection[prop_name] = gcnew String(strlist[selected_index]);

				break;
			}
/*
		case prop_mesh:
			{
				String^ model_name=gcnew String(i_GameProperty->get<sep3d::hierarchy_t>(i_Node).m_name.c_str());
				prop_collection[prop_name]=model_name;
				break;
			}
*/
			/*
			case prop_TREF_TEXTURE:
			{
			String^ texname=gcnew String(i_GameProperty->get<TREF_TEXTURE>(i_Node) ? i_GameProperty->get<TREF_TEXTURE>(i_Node)->GetName() : "");
			PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
			String::typeid,//PropertyGridEx::UIFileNameEditor::typeid,
			category_name,
			desc,
			texname,
			PropertyGridEx::UIFileNameEditor::typeid,
			System::Drawing::Design::UITypeEditor::typeid);

			ArrayList^ al=gcnew ArrayList;
			al->Add(gcnew PropertyGridEx::FileNameEditorAttr("texture files(*.dds;*.tga;*.png;*.jpg)|*.dds;*.tga;*.png;*.jpg","Textures"));
			ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);

			prop_collection->Properties->Add(ps);


			prop_collection[prop_name]=texname;
			break;
			}
			case prop_sound:
			{
			String^ soundname=gcnew String(i_GameProperty->get<sound_object_t>(i_Node).name.c_str());
			PropertyGridEx::PropertySpec^ ps=gcnew PropertyGridEx::PropertySpec(prop_name,
			PropertyGridEx::UIFileNameEditor::typeid,
			category_name,
			desc,
			soundname,
			PropertyGridEx::UIFileNameEditor::typeid,
			System::Drawing::Design::UITypeEditor::typeid);

			ArrayList^ al=gcnew ArrayList;
			al->Add(gcnew PropertyGridEx::FileNameEditorAttr("Sound files(*.wav;*.mp3)|*.wav;*.mp3","Sounds"));
			ps->Attributes=(array<System::Attribute^>^)al->ToArray(System::Attribute::typeid);

			prop_collection->Properties->Add(ps);


			prop_collection[prop_name]=soundname;
			break;
			}

			*/
/*
		case prop_natural_spline_t:
			{
				natural_spline_t& v=i_GameProperty->get<natural_spline_t>(i_Node);
				NaturalSplineObjectProp^ o=gcnew NaturalSplineObjectProp(&v,i_Node);
				prop_collection[prop_name]=o;
				break;
			}

		case prop_spherearray:
			{
				prop_array_t<sphere_t>& v=i_GameProperty->get<prop_array_t<sphere_t>>(i_Node);
				SphereArrayProp^ o=gcnew SphereArrayProp(&v,i_Node);
				prop_collection[prop_name]=o;
				break;
			}
*/

		case prop_array:
			{
				array_property_t* p=(array_property_t*)i_GameProperty;
				prop_array_base_t& a=i_GameProperty->get<prop_array_base_t>(i_Node);
				int size=a.get_size();

				switch (p->base_property->get_type())
				{
				case prop_int:
					{
						array<intprop^>^ intarray=gcnew array<intprop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							int val=p->base_property->get<int>((entity_t*)a.get_elem_ptr(n));
							intprop^ newbag=gcnew intprop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection[prop_name]=intarray;
						break;

						break;
					}
/*
				case prop_tick:
					{
						array<floatprop^>^ intarray=gcnew array<floatprop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float val=(float)p->base_property->get<int>((entity_t*)a.get_elem_ptr(n))/60;
							floatprop^ newbag=gcnew floatprop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection[prop_name]=intarray;
						break;
					}
*/
				case prop_float:
					{
						array<floatprop^>^ intarray=gcnew array<floatprop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float val=p->base_property->get<float>((entity_t*)a.get_elem_ptr(n));
							floatprop^ newbag=gcnew floatprop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection[prop_name]=intarray;
						break;
					}
				case prop_float2:
					{
						array<float2prop^>^ intarray=gcnew array<float2prop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float2 val=p->base_property->get<float2>((entity_t*)a.get_elem_ptr(n));
							float2prop^ newbag=gcnew float2prop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection[prop_name]=intarray;
						break;
					}
/*
				case prop_int2:
					{
						array<int2prop^>^ intarray=gcnew array<int2prop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							int2 val=p->base_property->get<int2>((entity_t*)a.get_elem_ptr(n));
							int2prop^ newbag=gcnew int2prop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection[prop_name]=intarray;
						break;
					}
*/
				case prop_float3:
					{
						array<float3prop^>^ intarray=gcnew array<float3prop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float3 val=p->base_property->get<float3>((entity_t*)a.get_elem_ptr(n));
							float3prop^ newbag=gcnew float3prop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection[prop_name]=intarray;
						break;
					}
				case prop_float4:
					{
						array<float4prop^>^ intarray=gcnew array<float4prop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							float4 val=p->base_property->get<float4>((entity_t*)a.get_elem_ptr(n));
							float4prop^ newbag=gcnew float4prop(nullptr,nullptr,val);
							intarray[n]=newbag;
						}
						prop_collection[prop_name]=intarray;
						break;
					}

				case prop_color4f:
					{
						break;
					}

/*
				case prop_sphere:
					{
						array<sphereprop^>^ intarray=gcnew array<sphereprop^>(a.get_size());
						for (int n=0; n<size; ++n)
						{
							sphere_t val=p->base_property->get<sphere_t>((entity_t*)a.get_elem_ptr(n));
							sphereprop^ newbag=gcnew sphereprop(val.center,val.radius);
							intarray[n]=newbag;
						}
						prop_collection[prop_name]=intarray;
						break;
					}
*/

				default:
					ASSERT(0);
				}
				break;
			}

		default:
			ASSERT(0);
		}
	}














	void get_property_from_grid(entity_t* i_Node,property_t* i_GameProperty,System::Object^ val)
	{
		switch (i_GameProperty->get_type())
		{
		case prop_color4f:
			{
				if (val->GetType()!=String::typeid)
				{
					ASSERT(0);
					return;
				}
				String^ str=(String^)val;
				array<String^>^ sep=gcnew array<String^>{";"};
				array<String^>^ arr=str->Split(sep,System::StringSplitOptions::None);

				color4f c(1,1,1,1);
				for (int n=0; n<min(arr->Length,4); ++n)
				{
//					c[n]=Convert::ToSingle(arr[n],CultureInfo::InvariantCulture);
					c[n]=Single::Parse(arr[n])/255;
				}
				i_GameProperty->set<color4f>(i_Node,c);
				break;
			}
		case prop_json_property:
			{
				String^ str=(String^)val;
				char ch[16384];
				String_to_string(str,ch);
				json_object_t* o=&i_GameProperty->get<json_object_t>(i_Node);
				json_object_t* no=generate_json_map(string("{")+string(ch)+string("}"));

				if (no)
					o->copy(*no);
				delete no;

				break;
			}
		case prop_int:
			{
				int i=(int)val;
				i_GameProperty->set<int>(i_Node,i);
				break;
			}

		case prop_float:
			{
				float f=(float)val;
				i_GameProperty->set<float>(i_Node,f);
				break;
			}

		case prop_angle:
			{
				float f=(float)val/RAD2DEG;
				i_GameProperty->set<float>(i_Node,f);
				break;
			}

		case prop_stringlist:
			{
//				array<String^>^ arr=(array<String^>^)val;
				PropertyGridEx::UIStringList^ arr;

				if (val->GetType()==String::typeid)
					arr=gcnew PropertyGridEx::UIStringList((String^)(val));
				else
					arr=(PropertyGridEx::UIStringList^)val;

				vector<string> v;
				for (int n=0; n<arr->Value->Count; ++n)
				{
					char ch[16384];
					String_to_string(arr->Value[n],ch);
					v.push_back(ch);
				}
				i_GameProperty->set<vector<string> >(i_Node,v);
				break;
			}
		
		case prop_string:
			{
				String^ Str=(String^)val;
				char ch[16384];
				String_to_string(Str,ch);
				i_GameProperty->set<string>(i_Node,string(ch));
				break;
			}
		case prop_stringhash:
			{
				String^ Str=(String^)val;
				char ch[16384];
				String_to_string(Str,ch);
				i_GameProperty->set<stringhash>(i_Node,stringhash::get(ch));
				break;
			}

		case prop_float3:
			{
				float3prop^ v=(float3prop^)val;
				i_GameProperty->set<float3>(i_Node,v->get());
				break;
			}
		case prop_float4:
			{
				float4prop^ v=(float4prop^)val;
				i_GameProperty->set<float4>(i_Node,v->get());
				break;
			}
		case prop_float2:
			{
				float2prop^ v=(float2prop^)val;
				i_GameProperty->set<float2>(i_Node,v->get());
				break;
			}
/*
		case prop_int2:
			{
				int2prop^ v=(int2prop^)val;
				i_GameProperty->set<int2>(i_Node,v->get());
				break;
			}
*/
/*
		case prop_cColor:
			{
				System::Drawing::Color col=(System::Drawing::Color)val;
				i_GameProperty->set<cColor>(i_Node,cColor(col.A,col.R,col.G,col.B));
				break;
			}
*/


		case prop_float4x4:
			{
				float4x4prop^ v=(float4x4prop^)val;
				i_GameProperty->set<float4x4>(i_Node,v->get());
				break;
			}

		case prop_bool:
			{
				bool b=bool(val);
				i_GameProperty->set<bool>(i_Node,b);
				break;
			}
		case prop_array:
			{
				array_property_t* p=(array_property_t*)i_GameProperty;
				prop_array_base_t& a=i_GameProperty->get<prop_array_base_t>(i_Node);

				switch (p->base_property->get_type())
				{
				case prop_int:
					{
						array<intprop^>^ intarray=(array<intprop^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							int i=intarray[n]->get();
							p->base_property->set<int>(a.get_elem_ptr(n),i);
						}
						break;
					}
/*
				case prop_tick:
					{
						array<floatprop^>^ intarray=(array<floatprop^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							floatprop^ v=intarray[n];
							p->base_property->set<int>(a.get_elem_ptr(n),(int)(v->get()*60));
						}
						break;
					}
*/
				case prop_float:
					{
						array<floatprop^>^ intarray=(array<floatprop^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							float f=intarray[n]->get();
							p->base_property->set<float>(a.get_elem_ptr(n),f);
						}
						break;
					}
				case prop_float2:
					{
						array<float2prop^>^ intarray=(array<float2prop^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							float2prop^ v=intarray[n];
							p->base_property->set<float2>(a.get_elem_ptr(n),v->get());
						}
						break;
					}
/*
				case prop_int2:
					{
						array<int2prop^>^ intarray=(array<int2prop^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							int2prop^ v=intarray[n];
							p->base_property->set<int2>(a.get_elem_ptr(n),v->get());
						}
						break;
					}
*/
				case prop_float3:
					{
						array<float3prop^>^ intarray=(array<float3prop^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							float3prop^ v=intarray[n];
							p->base_property->set<float3>(a.get_elem_ptr(n),v->get());
						}
						break;
					}
				case prop_float4:
					{
						array<float4prop^>^ intarray=(array<float4prop^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							float4prop^ v=intarray[n];
							p->base_property->set<float4>(a.get_elem_ptr(n),v->get());
						}
						break;
					}
/*
				case prop_spline:
					{
						array<NaturalSplineNodeProp^>^ intarray=(array<NaturalSplineNodeProp^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							NaturalSplineNodeProp^ v=intarray[n];
							natural_spline_node e=v->get();
							p->base_property->set<natural_spline_node>(a.get_elem_ptr(n),e);
						}
						break;
					}
				case prop_hermite_spline:
					{
						array<HermiteSplineNodeProp^>^ intarray=(array<HermiteSplineNodeProp^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							HermiteSplineNodeProp^ v=intarray[n];
							hermite_spline_node e=v->get();
							p->base_property->set<hermite_spline_node >(a.get_elem_ptr(n),e);
						}
						break;
					}
				case prop_tcb_spline:
					{
						array<TCBSplineNodeProp^>^ intarray=(array<TCBSplineNodeProp^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							TCBSplineNodeProp^ v=intarray[n];
							tcb_spline_node e=v->get();
							p->base_property->set<tcb_spline_node >(a.get_elem_ptr(n),e);
						}
						break;
					}
					*/
/*
				case prop_sphere:
					{
						array<sphereprop^>^ intarray=(array<sphereprop^>^ )val;
						a.resize_array(intarray->Length);
						for (int n=0; n<intarray->Length; ++n)
						{
							sphereprop^ v=intarray[n];
							float3 c=v->get_center();
							float r=v->get_radius();
							p->base_property->set<sphere_t>(a.get_elem_ptr(n),sphere_t(c,r));
						}
						break;
					}
*/
				default:
					ASSERT(0);
				}
				break;
			}


/*
		case prop_tick:
			{
				float f=float(val);
				i_GameProperty->set<int>(i_Node,(int)(f*60));
				break;
			}
		case prop_mesh:
			{
				String^ Str=(String^)val;
				char ch[1024];
				String_to_string(Str,ch);
				((mesh_property_t*)i_GameProperty)->set_mesh(i_Node,stringhash::get(ch));
				break;
			}
*/
			/*
		case prop_TREF_TEXTURE:
			{
				String^ Str=(String^)val;
				char ch[1024];
				String_to_string(Str,ch);
				((TREF_TEXTURE_property_t*)i_GameProperty)->set_TREF_TEXTURE(i_Node,string(ch));
				break;
			}
		case prop_sound:
			{
				String^ Str=(String^)val;
				char ch[1024];
				String_to_string(Str,ch);
				((sound_property_t*)i_GameProperty)->set_sound(i_Node,string(ch));
				break;
			}
*/
		case prop_enum:
			{
				String^ l=(String^)val;
				char** strlist=(char**)i_GameProperty->data;
				int selectedIndex=-1;
				for (int size=0; strlist[size];size++)
				{
					String^ s=gcnew String(strlist[size]);

					if (s==l)
					{
						selectedIndex=size;
						break;
					}
				}

				if (selectedIndex!=-1)
				i_GameProperty->set<int>(i_Node,selectedIndex);
				break;
			}


		default:
			//			assert(0);
			ASSERT(0);
		}
	}

	void add_property_to_grid(entity_t* ent,node* i_node, String^ crname,MyPropertyTable^ prop_collection)
	{

		if (i_node->children.size())
		{
			MyPropertyTable^ new_coll=gcnew MyPropertyTable(nullptr,ent);
			String^ bagname=(gcnew String(i_node->name));//->Replace("_"," ");
			prop_collection->Properties->Add(gcnew PropertyGridEx::PropertySpec(bagname, MyPropertyTable::typeid, crname, "", new_coll,
			System::Drawing::Design::UITypeEditor::typeid,
			ExpandableObjectConverter::typeid));
			prop_collection[bagname]=new_coll;

			for (unsigned int n=0; n<i_node->children.size(); ++n)
				add_property_to_grid(ent,i_node->children[n],crname,new_coll);
		}
		else
		{
			add_property_to_grid(ent,i_node->prop_desc,i_node->name,crname,prop_collection);
		}
	}

	void set_property_in_grid(entity_t* ent,node* i_node, String^ crname,MyPropertyTable^ prop_collection)
	{

		if (i_node->children.size())
		{
			String^ bagname=(gcnew String(i_node->name));

			for (unsigned int n=0; n<i_node->children.size(); ++n)
				set_property_in_grid(ent,i_node->children[n],crname,(MyPropertyTable^)prop_collection[bagname]);
		}
		else
		{
			set_property_in_grid(ent,i_node->prop_desc,i_node->name,crname,prop_collection);
		}
	}




	void MyPropertyTable::OnSetValue(PropertyGridEx::PropertySpecEventArgs^ e)
	{
		PropertyGridEx::PropertyTable::OnSetValue(e);

		PropertyNode^ hn=(PropertyNode^)UserData[e->Property->Name];

		if (hn!=nullptr)
		{
			System::Object^ val;

			if (parent==nullptr)
			{
				val=(*this)[e->Property->Name];
			}
			else
			{
				val=parent[hn->prop_name];
			}

			if (val!=nullptr)
			{
				get_property_from_grid(entity,hn->gamepropdesc,val);
				entity->onchangeproperty(hn->gamepropdesc->name);
//				SinemoraEditor::mainform->SetChanged();
			}

		}
	}



	System::Object^ UIColorEditor::EditValue(ITypeDescriptorContext^ context,
		System::IServiceProvider^ provider, System::Object^ value) 
	{
		if (context == nullptr || provider == nullptr || context->Instance == nullptr)
			return System::Drawing::Design::UITypeEditor::EditValue(provider, value);

		PropertyGridEx::PropertyBag::PropertySpecDescriptor^ splinedesc=(PropertyGridEx::PropertyBag::PropertySpecDescriptor^)context->PropertyDescriptor;

		String^ prop_name=context->PropertyDescriptor->Name;
		MyPropertyTable^ bag=(MyPropertyTable^)splinedesc->bag;
		ColorProp^ cp=(ColorProp^)bag[prop_name];

		ColorPicker::ColorPickerDialog^ ce=gcnew ColorPicker::ColorPickerDialog(cp);
//		ce->Show(interop::server::main_form);
		ce->Show(nullptr);//interop::server::main_form);
		return value;
	}

System::Object^ UITrackbarEditor::EditValue(ITypeDescriptorContext^ context,
			System::IServiceProvider^ provider,
			System::Object^ value)
		{

			_wfes = (IWindowsFormsEditorService^)provider->GetService(IWindowsFormsEditorService::typeid);

			if (_wfes == nullptr) { return value; }
			if (value == nullptr) { return value; }
			lattr = (PropertyGridEx::TrackbarEditorAttr^)context->PropertyDescriptor->Attributes[PropertyGridEx::TrackbarEditorAttr::typeid];

			if (lattr == nullptr)
				return value;

			prop_name=lattr->PropertyName;

			_control= gcnew TrackBar();
			//            _control.BorderStyle = BorderStyle.None;
			//            _control.SelectedIndexChanged += new EventHandler(ListItemSelected);

			//            _control.Height = _control.PreferredHeight;
			//            _control.Items.RemoveAt(_control.Items.Count - 1);

			if (!lattr->Type)
			{
				_control->Minimum = lattr->IntMinimum;
				_control->Maximum = lattr->IntMaximum;
				_control->Value = (int)value;
			}
			else
			{
				_control->Minimum=0;
				_control->Maximum=lattr->Granularity;
				_control->Value = Int32(((float)value-lattr->FloatMinimum)/(lattr->FloatMaximum-lattr->FloatMinimum)*lattr->Granularity);
			}

			_control->ValueChanged+=gcnew EventHandler(this,&UITrackbarEditor::ValueChanged);

			_wfes->DropDownControl(_control);

			if (!lattr->Type) //int
				value = _control->Value; 
			else if (lattr->Type==1) //float
				value=lattr->FloatMinimum+((float)_control->Value)/lattr->Granularity*(lattr->FloatMaximum-lattr->FloatMinimum);
			else //angle
				value=(lattr->FloatMinimum+((float)_control->Value)/lattr->Granularity*(lattr->FloatMaximum-lattr->FloatMinimum))*DEG2RAD;


			return value;
		}

	void UITrackbarEditor::ValueChanged(System::Object^ sender,EventArgs^ e)
	{
		char ch[16384];
		String_to_string(prop_name,ch);
		stringhash prop_hash=stringhash::get(ch);
		for (int n=0; n<interop::server::SelectedNodes->Count; ++n)
		{
			EntityTreeNode^ node=(EntityTreeNode^)interop::server::SelectedNodes[n];
			switch (lattr->Type)
			{
			case 0:
				{
					int intval=(int)(_control->Value);
					node->bag[prop_name]=intval;
					node->entity->get_metaobject()->get_property(prop_hash)->set<int>(node->entity,intval);
					break;
				}
			case 1:
				{
					float floatval=(float)(lattr->FloatMinimum+((float)_control->Value)/lattr->Granularity*(lattr->FloatMaximum-lattr->FloatMinimum));
					node->bag[prop_name]=floatval;
					node->entity->get_metaobject()->get_property(prop_hash)->set<float>(node->entity,floatval);
					break;
				}
			case 2:
				{
					int val=_control->Value;
					float floatval=(float)(lattr->FloatMinimum+((float)val)/lattr->Granularity*(lattr->FloatMaximum-lattr->FloatMinimum));
					node->bag[prop_name]=floatval*DEG2RAD;
					node->entity->get_metaobject()->get_property(prop_hash)->set<float>(node->entity,floatval*DEG2RAD);
					break;
				}
			}

			node->entity->onchangeproperty(stringhash::get(ch));
		}
		interop::server::need_refresh=true;
		interop::server::forced_render=true;
	}










	System::Object^ UITextboxEditor::EditValue(ITypeDescriptorContext^ context,
		System::IServiceProvider^ provider,
		System::Object^ value)
	{

		_wfes = (IWindowsFormsEditorService^)provider->GetService(IWindowsFormsEditorService::typeid);

		if (_wfes == nullptr) { return value; }
		_control= gcnew TextBox();
		//            _control.BorderStyle = BorderStyle.None;
		//            _control.SelectedIndexChanged += new EventHandler(ListItemSelected);

		//            _control.Height = _control.PreferredHeight;
		//            _control.Items.RemoveAt(_control.Items.Count - 1);
		_control->Multiline=true;
		_control->Text=(String^)value;
		_control->Height=max(_control->Height,_control->PreferredHeight*10);
		_control->Width*=4;
		_control->Width=max(_control->Width,_control->PreferredSize.Width);
		_control->ScrollBars=ScrollBars::Vertical;
		_control->TextChanged+=gcnew EventHandler(this,&UITextboxEditor::Text_Changed);


		_wfes->DropDownControl(_control);

		return _control->Text;
	}

	void UITextboxEditor::Text_Changed(System::Object^ sender, EventArgs^ e)
	{
		String^ str=(String^)_control->Text;
		char ch[16384];
		String_to_string(str,ch);
		json_object_t* no=generate_json_map(string("{")+string(ch)+string("}"));

		if (no)
		{
			_control->ForeColor=Color::FromArgb(0,0,0);
			delete no;
		}
		else
		{
			_control->ForeColor=Color::FromArgb(255,0,0);
		}


	}


	System::Object^ UIStringlistEditor::EditValue(ITypeDescriptorContext^ context,
		System::IServiceProvider^ provider,
		System::Object^ value)
	{

		_wfes = (IWindowsFormsEditorService^)provider->GetService(IWindowsFormsEditorService::typeid);

		if (_wfes == nullptr) { return value; }
		_control= gcnew TextBox();
		//            _control.BorderStyle = BorderStyle.None;
		//            _control.SelectedIndexChanged += new EventHandler(ListItemSelected);

		//            _control.Height = _control.PreferredHeight;
		//            _control.Items.RemoveAt(_control.Items.Count - 1);
		_control->Multiline=true;

		if (value!=nullptr)
		{
			PropertyGridEx::UIStringList^ val=(PropertyGridEx::UIStringList^)value;

			for (int n=0; n<val->Value->Count; ++n)
			{
				_control->Text+=val->Value[n];
				_control->Text+=Environment::NewLine;
			}
		}
		_control->Height=max(_control->Height,_control->PreferredHeight*10);
		_control->Width*=4;
		_control->Width=max(_control->Width,_control->PreferredSize.Width);
		_control->ScrollBars=ScrollBars::Vertical;
//		_control->TextChanged+=gcnew EventHandler(this,&SEPEditor::UITextboxEditor::Text_Changed);


		_wfes->DropDownControl(_control);

		array<String^>^ sep=gcnew array<String^>{Environment::NewLine};
		array<String^>^ arr=_control->Text->Split(sep,System::StringSplitOptions::None);
		PropertyGridEx::UIStringList^ ret= gcnew PropertyGridEx::UIStringList();
		int vege=arr->Length;
		for (int n=arr->Length-1; n>=0; --n)
		{
			if (arr[n]=="")
				vege--;
			else
				break;
		}
		for (int n=0; n<vege; ++n)
		{
			ret->Value->Add(arr[n]);
		}
		return ret;
	}







	//node
	char node_alloc_buf[4096*sizeof(node)];
	int alloc_ptr=0;

	void* node::operator new(size_t s)
	{
		++alloc_ptr;

		if (alloc_ptr==4096)
			alloc_ptr=0;

		return node_alloc_buf+(alloc_ptr*sizeof(node));
	}

	void node::operator delete(void*)
	{

	}


}
